﻿#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Controls;
using WpfFootball.Parser;
using System.Windows.Threading;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Diagnostics;
#endregion

namespace WpfFootball.UI
{
    /// <summary>
    /// Provides functions to manage the tabs, such as removing, adding and updating them when needed.
    /// </summary>
    public class TabManager
    {
        #region Delegates and Events
        public delegate void TabUpdatingHandler(object sender);
        public delegate void TabEndUpdateHandler(object sender);
        public event TabUpdatingHandler TabBeginUpdate;
        public event TabEndUpdateHandler TabEndUpdate;
        #endregion

        #region Fields
        private const double DEFAULT_TAB_WIDTH = 150;
        private const double DEFAULT_TAB_HEIGHT = 30;

        private TabControl tabControl;
        private IOManager ioManager;
        private DataParser dataParser;
        #endregion

        /// <summary>
        /// Creates a new TabManager.
        /// </summary>
        /// <param name="tabControl">The TabControl used in the application. Needed to allow the TabManager to manage the tabs.</param>
        public TabManager(TabControl tabControl)
        {
            this.tabControl = tabControl;
            ioManager = IOManager.Instance();
            InitTabs();
        }

        /// <summary>
        /// Retrieves a list with all registered teams and creates a tab item 
        /// for each of them.
        /// </summary>
        public void InitTabs()
        {
            List<string> managedTeams = ioManager.GetManagedTeams();
            tabControl.Items.Clear();

            foreach (string currentTeam in managedTeams)
            {
                AddTab(currentTeam, false);
            }
        }

        /// <summary>
        /// Notifies the underlaying IOManager to unregister a team 
        /// from the managed teams database.
        /// </summary>
        /// <param name="teamName">The name of the team to unregister.</param>
        private void UnregisterTeam(string teamName)
        {
            ioManager.RemoveManagedTeam(teamName);
            ioManager.DeleteViewsSettings(teamName);
        }

        /// <summary>
        /// Closes a tab. If there is only a tab on the tab control, the closing request will be
        /// ignored.
        /// </summary>
        /// <param name="tabItem">The tab to close.</param>
        private void CloseTab(TabItem tabItem)
        {
            if (tabControl.Items.Count > 1)
            {
                MessageBoxResult messageResult = MessageManager.ShowConfirmFollowTeam(tabItem.Tag.ToString());

                if (messageResult == MessageBoxResult.Yes)
                {
                    UnregisterTeam(tabItem.Tag as string);
                    tabControl.Items.Remove(tabItem);
                }
            }
            else
            {
                MessageManager.ShowCloseTabWarning();
            }
        }

        /// <summary>
        /// Helper function that creates a stack panel containing 
        /// the header content of a TabItem.
        /// </summary>
        /// <param name="teamName">The name of the team to vi shown on the header.</param>
        /// <param name="owner">The object that contains owns the created header object.</param>
        /// <returns>The content of a header, with all items stored in a stack panel.</returns>
        private StackPanel CreateTabHeader(string teamName, object owner)
        {
            StackPanel headerPanel = new StackPanel();
            headerPanel.Style = (Style)tabControl.FindResource("tabHeaderPanelStyle");

            TextBlock teamNameBlock = new TextBlock();
            teamNameBlock.Style = (Style)tabControl.FindResource("tabTeamNameBlockStyle");
            teamNameBlock.Text = teamName;

            if (teamName.Length > 13)
            {
                teamNameBlock.Margin = new Thickness(0, -2, 0, 0);
            }
            else
            {
                teamNameBlock.Margin = new Thickness(0, 5, 0, 0);
            }

            Image iconImage = new Image();
            iconImage.Style = (Style)tabControl.FindResource("tabIconStyle");
            iconImage.Source = new BitmapImage(new Uri(ioManager.GetTeamIconSource(teamName), UriKind.Relative));
            RenderOptions.SetBitmapScalingMode(iconImage, BitmapScalingMode.NearestNeighbor);

            Image closeButtonicon = new Image();
            closeButtonicon.Source = new BitmapImage(new Uri(@"/WpfFootball;component/Images/closeTab.png", UriKind.Relative));

            Button closeButton = new Button();
            closeButton.Style = (Style)tabControl.FindResource("closeTabButtonStyle");
            closeButton.Template = (ControlTemplate)tabControl.FindResource("closeButtonTemplate");
            closeButton.Click += new RoutedEventHandler(delegate { CloseTab(closeButton.Tag as TabItem); });
            closeButton.Content = closeButtonicon;
            closeButton.Tag = owner;

            headerPanel.Children.Add(iconImage);
            headerPanel.Children.Add(teamNameBlock);
            headerPanel.Children.Add(closeButton);

            return headerPanel;
        }

        /// <summary>
        /// Resizes the background image to fit the current tabControl dimensions.
        /// </summary>
        public void ResizeBackgroundLogo(object sender, SizeChangedEventArgs args)
        {
            Canvas canvas = sender as Canvas;
            Image logo = canvas.Children[0] as Image;

            if (canvas.ActualWidth > 500 && canvas.ActualHeight > 300)
            {
                logo.Width = canvas.ActualWidth;
                logo.Height = canvas.ActualHeight;
            }
        }

        /// <summary>
        /// Adds a new tab to the tab control at runtime with its standard components.
        /// </summary>
        /// <param name="teamName">The name of the team the tab belongs to.</param>
        /// <param name="setCurrent">Wether or not the created tab must be set as current.</param>
        public void AddTab(string teamName, bool setCurrent)
        {
            TabItem tabItem = new TabItem();
            tabItem.Style = (Style)tabControl.FindResource("tabItemStyle");
            tabItem.Header = CreateTabHeader(teamName, tabItem);
            tabItem.Tag = teamName;

            Canvas tabContentPanel = new Canvas();
            tabContentPanel.SizeChanged += ResizeBackgroundLogo;

            Image canvasLogo = new Image();
            canvasLogo.Style = (Style)tabControl.FindResource("canvasLogoStyle");
            tabContentPanel.Children.Add(canvasLogo);

            NextMatchViewer nextMatchViewer = new NextMatchViewer(teamName);
            nextMatchViewer.Tag = tabContentPanel;
            tabContentPanel.Children.Add(nextMatchViewer);

            UpcomingFixturesView fixturesView = new UpcomingFixturesView(teamName);
            fixturesView.Tag = tabContentPanel;
            tabContentPanel.Children.Add(fixturesView);

            NewsViewer newsViewer = new NewsViewer(teamName);
            newsViewer.Tag = tabContentPanel;
            tabContentPanel.Children.Add(newsViewer);

            FourmEntryViewer forumEntryViewer = new FourmEntryViewer(teamName);
            forumEntryViewer.Tag = tabContentPanel;
            tabContentPanel.Children.Add(forumEntryViewer);

            tabItem.Content = tabContentPanel;
            tabControl.Items.Add(tabItem);

            if (setCurrent)
            {
                tabControl.SelectedItem = tabItem;
            }
        }

        /// <summary>
        /// Updates the contents of the current tab.
        /// </summary>
        public void UpdateCurrentTab()
        {
            tabControl.Dispatcher.BeginInvoke(
                new Action(() =>
                {
                    Canvas panel = tabControl.SelectedContent as Canvas;

                    foreach (UIElement currentElement in panel.Children)
                    {
                        UpdatableView currentUpdatingView = currentElement as UpdatableView;
                        currentUpdatingView.Update();
                    }
                }
            ));
        }

        /// <summary>
        /// Notifies each of the active tabs to be terminated before the 
        /// application is being closed.
        /// </summary>
        public void TemrinateTabs()
        {
            tabControl.Dispatcher.BeginInvoke(
                new Action(() =>
                {
                    foreach (dynamic tabControlElement in tabControl.Items)
                    {
                        dynamic tabItemContent = tabControlElement.Content;

                        foreach (UIElement uiElement in tabItemContent.Children)
                        {
                            IClosableView currentView = uiElement as IClosableView;
                            if (currentView != null)
                            {
                                currentView.CloseView();
                            }
                        }
                    }
                }
            ));
        }
    }
}
